package com.yanqu.road.server.gameplayer.module.activity.diggold;

import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.activity.args.DigGoldAntiqueArgs;
import com.yanqu.road.entity.activity.diggold.config.DigGoldAntiqueConfig;
import com.yanqu.road.entity.activity.diggold.config.DigGoldConfig;
import com.yanqu.road.entity.activity.diggold.config.DigGoldStratumConfig;
import com.yanqu.road.entity.activity.diggold.data.DigGoldUserData;
import com.yanqu.road.entity.activity.diggold.entity.DigGoldBlockData;
import com.yanqu.road.entity.enums.activity.DigGold.eDigGoldBlockType;
import com.yanqu.road.entity.enums.eGamePlayerEventType;
import com.yanqu.road.entity.enums.eLogMoneyType;
import com.yanqu.road.entity.enums.eSystemId;
import com.yanqu.road.entity.log.LogDigGoldOperate;
import com.yanqu.road.entity.log.LogDigGoldPalaceReward;
import com.yanqu.road.logic.bussiness.activity.DigGoldBusiness;
import com.yanqu.road.pb.activity.DigGoldProto;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.base.GeneralModule;
import com.yanqu.road.server.gameplayer.module.player.CurrencyModule;
import com.yanqu.road.server.manger.activity.ActivityMgr;
import com.yanqu.road.server.manger.activity.DigMgr;
import com.yanqu.road.server.manger.activity.diggold.DigGoldMgr;

import com.yanqu.road.server.manger.config.SystemOpenMgr;
import com.yanqu.road.server.manger.log.AutoLogMgr;
import com.yanqu.road.server.protocol.ClientProtocol;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;

import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class DigGoldModule extends GeneralModule {

    private DigGoldUserData userData;

    @Override
    public void afterLogin() {
        syncConfig();
        syncUserData();
    }

    public DigGoldModule(GamePlayer player) {
        super(player);
    }

    @Override
    public boolean loadData() {
        ActivityInfo activityInfo = DigGoldMgr.getActivityInfo();
        if (activityInfo == null) {
            return true;
        }
        userData = DigGoldBusiness.getDigGoldUserData(activityInfo.getActivityId(), getUserId());
        return true;
    }

    @Override
    public boolean afterLoadData() {
        return true;
    }

    @Override
    public boolean saveData() {
        if (userData == null){
            return true;
        }
        if (userData.isInsertOption()){
            DigGoldBusiness.addDigGoldUserData(userData);
        }else if (userData.isUpdateOption()){
            DigGoldBusiness.updateDigGoldUserData(userData);
        }

        return true;
    }

    /**
     * 同步配置
     */
    public void syncConfig() {
        if (DigGoldMgr.getActivityInfo() == null) {
            return;
        }
        if (DigGoldMgr.getConfig() == null) {
            return;
        }
        DigGoldProto.DigGoldConfig.Builder configMsg = DigGoldMgr.getConfigMsg(player.getLanguage());
        if (configMsg == null) {
            return;
        }
        player.sendPacket(ClientProtocol.U_DIG_GOLD_SYNC_CONFIG, configMsg);
    }

    /**
     * 同步玩家数据
     */
    public void syncUserData() {
        if (DigGoldMgr.getActivityInfo() == null) {
            return;
        }
        if (!SystemOpenMgr.systemOpen(player, eSystemId.DigGold.getValue())) {
            return;
        }
        if (DigGoldMgr.getConfig() == null) {
            return;
        }
        initUserData();
        if (userData == null) {
            return;
        }
        //重新检测所有的块链接
        recheckAllBlockLink();
        //重新算古董声望
        reCalculateScore();
        DigGoldProto.DigGoldUserData.Builder builder = parseUserData();
        DigGoldProto.DigGoldUserDataSync.Builder msg = DigGoldProto.DigGoldUserDataSync.newBuilder();
        msg.setUserData(builder);
        player.sendPacket(ClientProtocol.U_DIG_GOLD_SYNC_USER_DATA, msg);
    }

    /**
     * 普通检测
     */
    public int simpleCheck(int activityId) {
        ActivityInfo activityInfo = DigGoldMgr.getActivityInfo();
        if (activityInfo == null) {
            return GameErrorCode.E_DIG_GOLD_NO_OPEN;
        }
        if (activityInfo.getActivityId() != activityId) {
            return GameErrorCode.E_DIG_GOLD_ACTIVITY_ID_ERROR;
        }
        if (!ActivityMgr.activityInTime(activityInfo)) {
            return GameErrorCode.E_DIG_GOLD_NO_IN_GAME_TIME;
        }
        if (!SystemOpenMgr.systemOpen(player, eSystemId.DigGold.getValue())) {
            return GameErrorCode.E_DIG_GOLD_NO_UNLOCK;
        }
        if (DigGoldMgr.getConfig() == null) {
            return GameErrorCode.E_DIG_GOLD_CONFIG_ERROR;
        }
        if (userData == null) {
            initUserData();
        }
        if (userData == null) {
            return GameErrorCode.E_DIG_GOLD_NO_OPEN;
        }
        return 0;

    }

    /**
     * 开挖 类型 1:挖 2:炸 3:钻
     */
    public int digGold(int activityId, int type, int x, int y) {
        int check = simpleCheck(activityId);
        if (check != 0) {
            return check;
        }
        //盘面开始行数
        int inCol = userData.getInCol();
        //盘面结束行数
        int endCol = userData.getInCol() + DigGoldMgr.getBoardY() - 1;
        //玩家当前分数
        long oldScore = userData.getScore();
        //获得积分
        long scoreGet = 0;
        Map<Integer,Integer> logAntiqueMap = new ConcurrentHashMap<>();

        DigGoldProto.DigGoldResp.Builder msg = DigGoldProto.DigGoldResp.newBuilder();
        msg.setType(type);
        msg.addAllOldBlock(parseBlockDataList(userData.getBlockDataList()));

        DigGoldConfig config = DigGoldMgr.getConfig();
        //查看目标是否超出盘面
        if (x < 0 || x >= DigGoldMgr.getBoardX()) {
            return GameErrorCode.E_DIG_GOLD_BLOCK_NOT_EXIST;
        }
        if (y < inCol || y > endCol) {
            return GameErrorCode.E_DIG_GOLD_BLOCK_BEYOND_MAP;
        }

        //取出操作方块
        DigGoldBlockData blockDataByXY = getBlockDataByXY(x, y, userData.getBlockDataList());
        if (blockDataByXY == null) {
            return GameErrorCode.E_DIG_GOLD_BLOCK_NOT_EXIST;
        }
        //复制一份 日志用
        DigGoldBlockData copy = blockDataByXY.copy();
        Property cost = new Property();
        Property reward = new Property();
        //用积分判断当前土层
        DigGoldStratumConfig stratum = DigGoldMgr.getStratum(userData.getScore());
//        System.out.println(userData.getInCol());
//        List<DigGoldBlockData> print = getBlockDataByYRange(inCol, endCol, userData.getBlockDataList());
//        printBlock(print);

        if (type == 1) {             // 纯挖
            //空地和地宫不能挖
            if (blockDataByXY.getType() == eDigGoldBlockType.space.getValue() || blockDataByXY.getType() == eDigGoldBlockType.palace.getValue()) {
                return GameErrorCode.E_DIG_GOLD_EMPTY_BLOCK_CAN_NO_DIG;
            }
            //如果没血了
            if (blockDataByXY.getHp() <= 0) {
                blockDataByXY.setType(eDigGoldBlockType.space.getValue());
                return GameErrorCode.E_DIG_GOLD_EMPTY_BLOCK_CAN_NO_DIG;
            }
            //第一行不判断
            if (y != 0) {
                //如果该方块之前已经链接过了不必判断
                if (!blockDataByXY.isLinkTop()){
                    //否则重新判断是否链接
                    int checkConnectTop = checkConnectTop(x, y);
                    if (checkConnectTop != 0) {
                        return checkConnectTop;
                    }
                }
            }

            //检测是否有道具
            cost.addProperty(config.getDigItemId(), BigInteger.ONE);
            cost.rideProperty(stratum.getMagnification());
            if (!player.getModule(CurrencyModule.class).removeCurrency(cost, eLogMoneyType.DigGold, eLogMoneyType.DigGoldDigCost)) {
                return GameErrorCode.E_DIG_GOLD_ITEM_NO_ENOUGH;
            }
            msg.addOperateBlock(parseBlockData(blockDataByXY));
            //格子扣血
            blockDataByXY.setHp(blockDataByXY.getHp() - 1);
            if (blockDataByXY.getHp() <= 0) {
                //变成空格
                blockDataByXY.setType(eDigGoldBlockType.space.getValue());
                int rewardId = blockDataByXY.getReward();
                //道具奖励
                if (rewardId >= 100000) {
                    Property singleReward;
                    //如果是铲子奖励 需要随机数量
                    if (rewardId == config.getDigItemId()){
                        BigInteger randomShovelRewardNum = DigGoldMgr.getRandomShovelRewardNum();
                        singleReward = new Property(rewardId, randomShovelRewardNum);
                    }else { // 其他的默认为1
                        singleReward = new Property(rewardId, BigInteger.ONE);
                    }
                    //奖励翻倍
                    singleReward.rideProperty(stratum.getMagnification());
                    //取出奖励
                    reward.addProperty(singleReward);

                    DigGoldProto.DigGoldRewardData.Builder rewardData = DigGoldProto.DigGoldRewardData.newBuilder();
                    rewardData.setX(blockDataByXY.getX());
                    rewardData.setY(blockDataByXY.getY());
                    rewardData.setReward(PropertyHelper.parsePropertyToString(singleReward));

                    msg.addReward(rewardData);
                } else if (rewardId > 0) { //古董奖励
                    addAntique(rewardId, stratum.getMagnification());
                    DigGoldProto.RewardAntiqueData.Builder antiqueRewardData = DigGoldProto.RewardAntiqueData.newBuilder();
                    antiqueRewardData.setX(blockDataByXY.getX());
                    antiqueRewardData.setY(blockDataByXY.getY());

                    DigGoldProto.DigGoldAntiqueData.Builder antiqueData = DigGoldProto.DigGoldAntiqueData.newBuilder();
                    antiqueData.setAntiqueId(rewardId);
                    antiqueData.setNum(stratum.getMagnification());

                    antiqueRewardData.setAntiqueData(antiqueData);
                    msg.addAntiqueData(antiqueRewardData);
                    logAntiqueMap.put(rewardId, stratum.getMagnification());
                }
            }
            long scorePerItem = config.getScorePerItem();
            scoreGet = scorePerItem * stratum.getMagnification();
            userData.setScore(userData.getScore() + scoreGet);
            player.getModule(CurrencyModule.class).addCurrency(new Property(config.getScoreItemId(), scoreGet), eLogMoneyType.DigGold, eLogMoneyType.DigGoldDigGet);

            checkMapMoveDown();
        } else if (type == 2) {
            //检测是否有道具
            cost.addProperty(config.getBombItemId(), BigInteger.ONE);
            cost.rideProperty(stratum.getMagnification());
            if (!player.getModule(CurrencyModule.class).removeCurrency(cost, eLogMoneyType.DigGold, eLogMoneyType.DigGoldDigCost)) {
                return GameErrorCode.E_DIG_GOLD_ITEM_NO_ENOUGH;
            }
            //炸
            boolean bombSomeThing = false;
            //拿出当前盘面
            List<DigGoldBlockData> blockDataByYRange = getBlockDataByYRange(inCol, endCol, userData.getBlockDataList());
            for (DigGoldBlockData blockData : blockDataByYRange) {
                if ((blockData.getX() == blockDataByXY.getX() && blockData.getY() == blockDataByXY.getY() + 1) ||
                        (blockData.getX() == blockDataByXY.getX() && blockData.getY() == blockDataByXY.getY() - 1) ||
                        (blockData.getX() == blockDataByXY.getX() && blockData.getY() == blockDataByXY.getY() + 2) ||
                        (blockData.getX() == blockDataByXY.getX() && blockData.getY() == blockDataByXY.getY() - 2) ||
                        (blockData.getX() == blockDataByXY.getX() + 1 && blockData.getY() == blockDataByXY.getY()) ||
                        (blockData.getX() == blockDataByXY.getX() - 1 && blockData.getY() == blockDataByXY.getY()) ||
                        (blockData.getX() == blockDataByXY.getX() + 2 && blockData.getY() == blockDataByXY.getY()) ||
                        (blockData.getX() == blockDataByXY.getX() - 2 && blockData.getY() == blockDataByXY.getY()) ||
                        (blockData.getX() == blockDataByXY.getX() + 1 && blockData.getY() == blockDataByXY.getY() + 1) ||
                        (blockData.getX() == blockDataByXY.getX() - 1 && blockData.getY() == blockDataByXY.getY() - 1) ||
                        (blockData.getX() == blockDataByXY.getX() + 1 && blockData.getY() == blockDataByXY.getY() - 1) ||
                        (blockData.getX() == blockDataByXY.getX() - 1 && blockData.getY() == blockDataByXY.getY() + 1) ||
                        blockData.equals(blockDataByXY)
                ) {
                    if (blockData.getType() == eDigGoldBlockType.space.getValue() || blockData.getType() == eDigGoldBlockType.palace.getValue()) {
                        msg.addOperateBlock(parseBlockData(blockData));
                    } else {
                        bombSomeThing = true;
                        //清空血量
                        blockData.setHp(0);
                        //变成空格
                        blockData.setType(eDigGoldBlockType.space.getValue());
                        //拿出奖励
                        int rewardId = blockData.getReward();
                        //道具奖励
                        if (rewardId >= 100000) {
                            Property singleReward;
                            //如果是铲子奖励 需要随机数量
                            if (rewardId == config.getDigItemId()){
                                BigInteger randomShovelRewardNum = DigGoldMgr.getRandomShovelRewardNum();
                                singleReward = new Property(rewardId, randomShovelRewardNum);
                            }else { // 其他的默认为1
                                singleReward = new Property(rewardId, BigInteger.ONE);
                            }
                            //奖励翻倍
                            singleReward.rideProperty(stratum.getMagnification());
                            //取出奖励
                            reward.addProperty(singleReward);


                            DigGoldProto.DigGoldRewardData.Builder rewardData = DigGoldProto.DigGoldRewardData.newBuilder();
                            rewardData.setX(blockData.getX());
                            rewardData.setY(blockData.getY());
                            rewardData.setReward(PropertyHelper.parsePropertyToString(singleReward));

                            msg.addReward(rewardData);
                        } else if (rewardId > 0) { //古董奖励
                            addAntique(rewardId, stratum.getMagnification());
                            DigGoldProto.RewardAntiqueData.Builder antiqueRewardData = DigGoldProto.RewardAntiqueData.newBuilder();
                            antiqueRewardData.setX(blockData.getX());
                            antiqueRewardData.setY(blockData.getY());

                            DigGoldProto.DigGoldAntiqueData.Builder antiqueData = DigGoldProto.DigGoldAntiqueData.newBuilder();
                            antiqueData.setAntiqueId(rewardId);
                            antiqueData.setNum(stratum.getMagnification());

                            antiqueRewardData.setAntiqueData(antiqueData);
                            msg.addAntiqueData(antiqueRewardData);
                            if (logAntiqueMap.containsKey(rewardId)) {
                                logAntiqueMap.put(rewardId, logAntiqueMap.get(rewardId) + stratum.getMagnification());
                            } else {
                                logAntiqueMap.put(rewardId, stratum.getMagnification());
                            }
                        }
                        msg.addOperateBlock(parseBlockData(blockData));

                    }
                }

            }
            //等所有方块都炸掉了之后再坚持是否要下移
            checkMapMoveDown();
            //没有炸到东西 返还道具
            if (!bombSomeThing) {
                player.getModule(CurrencyModule.class).addCurrency(cost, eLogMoneyType.DigGold, eLogMoneyType.DigGoldDigCostReBack);
                return GameErrorCode.E_DIG_GOLD_BOMB_NOTHING;
            }
        } else if (type == 3) {
            //检测是否有道具
            cost.addProperty(config.getDrillItemId(), BigInteger.ONE);
            cost.rideProperty(stratum.getMagnification());
            if (!player.getModule(CurrencyModule.class).removeCurrency(cost, eLogMoneyType.DigGold, eLogMoneyType.DigGoldDigCost)) {
                return GameErrorCode.E_DIG_GOLD_ITEM_NO_ENOUGH;
            }
            //钻
            //拿出当前盘面
            List<DigGoldBlockData> blockDataByYRange = getBlockDataByYRange(inCol, endCol, userData.getBlockDataList());
            List<DigGoldBlockData> blockDataByX = getBlockDataByX(blockDataByXY.getX(), blockDataByYRange);

            if (blockDataByXY.getX() > 0 && getBlockDataByXY(blockDataByXY.getX() - 1, endCol, blockDataByYRange) != null) {
                blockDataByX.add(getBlockDataByXY(blockDataByXY.getX() - 1, endCol, blockDataByYRange));
            }
            if (blockDataByXY.getX() < DigGoldMgr.getBoardX() - 1 && getBlockDataByXY(blockDataByXY.getX() + 1, endCol, blockDataByYRange) != null) {
                blockDataByX.add(getBlockDataByXY(blockDataByXY.getX() + 1, endCol, blockDataByYRange));
            }
            boolean bombSomeThing = false;
            for (DigGoldBlockData data : blockDataByX) {
                if (data.getType() == eDigGoldBlockType.space.getValue() || data.getType() == eDigGoldBlockType.palace.getValue()) {
                    msg.addOperateBlock(parseBlockData(data));
                } else {
                    bombSomeThing = true;
                    //清空血量
                    data.setHp(0);
                    //变成空格
                    data.setType(eDigGoldBlockType.space.getValue());
                    //拿出奖励
                    int rewardId = data.getReward();
                    //道具奖励
                    if (rewardId >= 100000) {
                        Property singleReward;
                        //如果是铲子奖励 需要随机数量
                        if (rewardId == config.getDigItemId()){
                            BigInteger randomShovelRewardNum = DigGoldMgr.getRandomShovelRewardNum();
                            singleReward = new Property(rewardId, randomShovelRewardNum);
                        }else { // 其他的默认为1
                            singleReward = new Property(rewardId, BigInteger.ONE);
                        }
                        //奖励翻倍
                        singleReward.rideProperty(stratum.getMagnification());
                        //取出奖励
                        reward.addProperty(singleReward);

                        DigGoldProto.DigGoldRewardData.Builder rewardData = DigGoldProto.DigGoldRewardData.newBuilder();
                        rewardData.setX(data.getX());
                        rewardData.setY(data.getY());
                        rewardData.setReward(PropertyHelper.parsePropertyToString(singleReward));

                        msg.addReward(rewardData);
                    } else if (rewardId > 0) { //古董奖励
                        addAntique(rewardId, stratum.getMagnification());
                        DigGoldProto.RewardAntiqueData.Builder antiqueRewardData = DigGoldProto.RewardAntiqueData.newBuilder();
                        antiqueRewardData.setX(data.getX());
                        antiqueRewardData.setY(data.getY());

                        DigGoldProto.DigGoldAntiqueData.Builder antiqueData = DigGoldProto.DigGoldAntiqueData.newBuilder();
                        antiqueData.setAntiqueId(rewardId);
                        antiqueData.setNum(stratum.getMagnification());

                        antiqueRewardData.setAntiqueData(antiqueData);
                        msg.addAntiqueData(antiqueRewardData);
                        if (logAntiqueMap.containsKey(rewardId)) {
                            logAntiqueMap.put(rewardId, logAntiqueMap.get(rewardId) + stratum.getMagnification());
                        } else {
                            logAntiqueMap.put(rewardId, stratum.getMagnification());
                        }
                    }
                    msg.addOperateBlock(parseBlockData(data));

                }
            }
            checkMapMoveDown();
            if (!bombSomeThing) {
                //没有炸到东西 返还道具
                player.getModule(CurrencyModule.class).addCurrency(cost, eLogMoneyType.DigGold, eLogMoneyType.DigGoldDigCostReBack);
                return GameErrorCode.E_DIG_GOLD_BOMB_NOTHING;
            }
        }  else {
            return GameErrorCode.E_DIG_GOLD_OPERATE_TYPE_ERROR;
        }
        //检测所有连接
        recheckAllBlockLink();
        //检测土层变化
        checkStratumChange();
        player.getModule(CurrencyModule.class).addCurrency(reward, eLogMoneyType.DigGold, eLogMoneyType.DigGoldDigGet);
        //玩家数据先更新
        userData.setUpdateOption();
        LogDigGoldOperate log = new LogDigGoldOperate(activityId,getUserId(),inCol,type,PropertyHelper.parsePropertyToString(cost),copy,oldScore,scoreGet,userData.getScore(),logAntiqueMap,PropertyHelper.parsePropertyToString(reward),new Date());
        AutoLogMgr.add(log);
//        print = getBlockDataByYRange(userData.getInCol(), userData.getInCol() + DigGoldMgr.getBoardY()-1 , userData.getBlockDataList());
//
//        System.out.println("incol" + userData.getInCol());
//        printBlock(print);
        msg.setRet(0);
        //msg.addAllNewBlock(parseBlockDataList(userData.getBlockDataList()));
        msg.setUserData(parseUserData());
        player.sendPacket(ClientProtocol.U_DIG_GOLD_OPERATE, msg);


        return 0;

    }

    /**
     * 获取地宫宝箱奖励
     * @param activityId
     * @param mapIndex
     * @param reqBoxIndexList
     * @return
     */

    public int getPalaceBoxReward(int activityId,int mapIndex,List<Integer> reqBoxIndexList){
        int check = simpleCheck(activityId);
        if (check != 0){
            return check;
        }
        DigGoldConfig config = DigGoldMgr.getConfig();
        //如果玩家身上都没有这个地图id
        if (!userData.getBoxList().containsKey(mapIndex)) {
            return GameErrorCode.E_DIG_GOLD_NOT_PALACE_BLOCK;
        }
        //检测是否领取过
        List<Integer> remainBoxList = userData.getBoxList().get(mapIndex);
        if (remainBoxList.isEmpty()){
            return GameErrorCode.E_DIG_GOLD_HAS_GET_BOX;
        }

        List<Integer> canGetBox = new ArrayList<>();
        for (int reqGetBoxIndex : reqBoxIndexList){
            //如果剩余的box里面有请求的
            if (remainBoxList.contains(reqGetBoxIndex) && !canGetBox.contains(reqGetBoxIndex)){
                canGetBox.add(reqGetBoxIndex);
            }
        }
        if (canGetBox.isEmpty()){
            return GameErrorCode.E_DIG_GOLD_HAS_GET_BOX;
        }

        DigGoldProto.GetPalaceRewardResp.Builder builder = DigGoldProto.GetPalaceRewardResp.newBuilder();
        builder.setRet(0);

        for (int canGetIndex :canGetBox){
            if (!remainBoxList.contains(canGetIndex)){
                continue;
            }
            int stratumId = 1;
            for (Map.Entry<Integer,Integer> entry:userData.getStratumIndexMap().entrySet()){
                if (entry.getKey() > stratumId && mapIndex >= entry.getValue()){
                    stratumId = entry.getKey();
                }
            }
            DigGoldStratumConfig stratum = DigGoldMgr.getStratumConfigById(stratumId);
            if (stratum == null) {
                return GameErrorCode.E_DIG_GOLD_CONFIG_ERROR;
            }
            int rewardIndex = config.getBoxNumPerPalace()-remainBoxList.size();
            if (rewardIndex < 0){
                log.error("dig gold get palace box reward error rewardIndex < 0,user:{}",getUserId());
                return GameErrorCode.E_DIG_GOLD_CONFIG_ERROR;
            }
            if (!stratum.getRewardMap().containsKey(rewardIndex)){
                log.error("dig gold get palace box reward error rewardIndex not exist,user:{}",getUserId());
                return GameErrorCode.E_DIG_GOLD_CONFIG_ERROR;
            }
            String reward = stratum.getRewardMap().get(rewardIndex);
            //先移除index 再领奖
            remainBoxList.removeIf(integer -> integer == canGetIndex);
            //更新数据
            userData.setUpdateOption();
            //发奖
            Property property = PropertyHelper.parseNewStringToProperty(reward);
            for (Map.Entry<Integer,BigInteger>entry:property.getGoods().entrySet()){
                if (entry.getKey() >= 100000){
                    //道具就加道具
                    player.getModule(CurrencyModule.class).addCurrency(new Property(entry.getKey(),entry.getValue()), eLogMoneyType.DigGold, eLogMoneyType.DigGoldPalaceGet);
                }else if (entry.getKey()>0){
                    addAntique(entry.getKey(),entry.getValue().intValue());
                }
            }
            builder.addReward(PropertyHelper.parsePropertyToString(property));
            LogDigGoldPalaceReward log = new LogDigGoldPalaceReward(activityId,getUserId(),userData.getInCol(),mapIndex,canGetIndex,PropertyHelper.parsePropertyToString(property),new Date());
            AutoLogMgr.add(log);
        }
        builder.setUserData(parseUserData());
        player.sendPacket(ClientProtocol.U_DIG_GOLD_GET_PALACE_REWARD, builder);

        return 0;
    }


    private void printBlock(List<DigGoldBlockData> data) {
        sortBlock(data);

    }

    public static void sortBlock(List<DigGoldBlockData> data) {
        DigGoldMgr.sortBlock(data);
        for (DigGoldBlockData digGoldBlockData : data) {
            System.out.print("x=" + digGoldBlockData.getX() + " ");
            System.out.print("y=" + digGoldBlockData.getY() + " ");
            System.out.print("hp=" + digGoldBlockData.getHp() + " ");
            System.out.print("type=" + digGoldBlockData.getType() + " ");
            System.out.print("mapIndex=" + digGoldBlockData.getMap() + " ");
            System.out.println();
        }
    }

    /**
     * 增加古董
     */
    public void addAntique(int antiqueId, int num) {
        Map<Integer, Integer> antiqueNumMap = userData.getAntiqueNumMap();
        if (antiqueNumMap == null) {
            antiqueNumMap = new ConcurrentHashMap<>();
            userData.setAntiqueNumMap(antiqueNumMap);
        }
        if (antiqueNumMap.containsKey(antiqueId)) {
            antiqueNumMap.put(antiqueId, antiqueNumMap.get(antiqueId) + num);
        } else {
            antiqueNumMap.put(antiqueId, num);
        }
        reCalculateScore();
        userData.setUpdateOption();
    }

    /**
     * 重新计算玩家的古董积分,成就 并更新排行榜
     */
    public void reCalculateScore() {
        if (userData == null){
            return;
        }
        long score = 0;
        Map<Integer, Integer> antiqueNumMap = userData.getAntiqueNumMap();
        if (antiqueNumMap == null) {
            return;
        }
        for (Map.Entry<Integer, Integer> entry : antiqueNumMap.entrySet()) {
            int antiqueId = entry.getKey();
            int num = entry.getValue();
            //更新古董数量成就
            player.notifyListener(eGamePlayerEventType.DigGoldAntiqueCondition.getValue(), new DigGoldAntiqueArgs(antiqueId, num));
            DigGoldAntiqueConfig antiqueConfig = DigGoldMgr.getDigGoldAntiqueConfigById(antiqueId);
            if (antiqueConfig == null) {
                log.error("dig gold antique config not exist,userId{} antiqueId:{}", getUserId(),antiqueId);
                continue;
            }
            score += antiqueConfig.getValue() * (long)num;
        }
        userData.setAntiqueScore(score);
        //更新古董积分成就
        player.notifyListener(eGamePlayerEventType.DigGoldAntiqueScoreCondition.getValue(), score);
        //积分排行榜 现在暂时是古董积分
        player.notifyListener(eGamePlayerEventType.DigGoldScoreRank.getValue(), userData.getAntiqueScore());

    }


    /**
     * 初始化玩家数据
     */
    public void initUserData() {
        ActivityInfo activityInfo = DigGoldMgr.getActivityInfo();
        if (activityInfo == null) {
            return;
        }
        if (DigGoldMgr.getConfig()==null){
            return;
        }
        if (userData != null && userData.getActivityId() == activityInfo.getActivityId()) {
            return;
        }
        DigGoldUserData tmpUserData = new DigGoldUserData();
        tmpUserData.setActivityId(activityInfo.getActivityId());
        tmpUserData.setUserId(getUserId());
        tmpUserData.setInCol(0);
        List<DigGoldBlockData> digGoldUpBlockData = DigGoldMgr.getMapByIndex(0,userData);
        if (digGoldUpBlockData == null || digGoldUpBlockData.size() != DigGoldMgr.getBoardX() * DigGoldMgr.getBoardY()) {
            log.error("DigGoldModule initUserData generateRandomMapData error activityId:{},mapIndex:{}", activityInfo.getActivityId(), 0);
            return;
        }

        List<DigGoldBlockData> digGoldDownBlockData = DigGoldMgr.getMapByIndex(1,userData);
        if (digGoldDownBlockData == null || digGoldDownBlockData.size() != DigGoldMgr.getBoardX() * DigGoldMgr.getBoardY()) {
            log.error("DigGoldModule initUserData generateRandomMapData error activityId:{},mapIndex :{}", activityInfo.getActivityId(), 1);
            return;
        }
        tmpUserData.setBlockDataList(new ArrayList<>());
        tmpUserData.getBlockDataList().addAll(digGoldUpBlockData);
        tmpUserData.getBlockDataList().addAll(digGoldDownBlockData);
        tmpUserData.setBoxList(new ConcurrentHashMap<>());
        tmpUserData.getBoxList().put(0,DigGoldMgr.getBoxMapByIndex(false));
        tmpUserData.getBoxList().put(1,DigGoldMgr.getBoxMapByIndex(false));

        tmpUserData.setMapIndex(1);
        tmpUserData.setAntiqueNumMap(new ConcurrentHashMap<>());
        tmpUserData.setScore(0);
        tmpUserData.setAntiqueScore(0);
        tmpUserData.setNoPalaceTime(0);
        tmpUserData.setStratumIndexMap(new ConcurrentHashMap<>());
        tmpUserData.getStratumIndexMap().put(1,0);
        tmpUserData.setInsertOption();

        userData = tmpUserData;
    }

    /**
     * 重新检测所有方块
     */
    public void recheckAllBlockLink(){
        if (userData == null) {
            log.error("DigGoldModule recheckAllBlockLink error userData is null,user:{}", getUserId());
            return;
        }
        int inCol = userData.getInCol();                    //玩家的第一行在地图的第几列
        int endCol = inCol + DigGoldMgr.getBoardY() - 1;      //玩家的最后一行在地图的第几列
        getBlockDataByYRange(inCol,endCol,userData.getBlockDataList()).forEach(this::checkConnectTop);
    }


    /**
     * 检测地图是否要向下移动
     */
    public void checkMapMoveDown() {
        if (userData == null) {
            return;
        }
        int inCol = userData.getInCol();                    //玩家的第一行在地图的第几列
        int endCol = inCol + DigGoldMgr.getBoardY() - 1;      //玩家的最后一行在地图的第几列
        //需要检测设置为true
        boolean needCheck = true;

        while (needCheck) {
            needCheck = false;
            //拿出最后一行的数据
            //log.error("checkMapMoveDown inCol:{},endCol:{}", inCol, endCol);

            List<DigGoldBlockData> blockDataByY = getBlockDataByY(endCol, userData.getBlockDataList());
            //如果最后一行有空方块并且与顶部联通
            for (DigGoldBlockData blockData : blockDataByY) {
                if ((blockData.getType() == eDigGoldBlockType.space.getValue() || blockData.getType() == eDigGoldBlockType.palace.getValue()) && checkConnectTop(blockData) == 0) {
                    //log.error("MoveDown blockData.getX():{},blockData.getY():{}", blockData.getX(), blockData.getY());
                    moveDown();
                    //还需要继续检测
                    needCheck = true;
                    endCol = userData.getInCol() + DigGoldMgr.getBoardY() - 1;
                    break;
                }
            }
        }
    }

    /**
     * 检测土层变化
     */
    public void checkStratumChange() {
        if (userData == null) {
            return;
        }
        DigGoldStratumConfig stratum = DigGoldMgr.getStratum(userData.getScore());
        if (stratum == null) {
            log.error("DigGoldModule checkSturatumChange error stratum is null,userId:{},score:{}", getUserId(), userData.getScore());
            return;
        }
        synchronized (userData){
            if (userData.getStratumIndexMap().containsKey(stratum.getId())) {
                return;
            }else {
                userData.changeStratumIndexMap(stratum.getId(),userData.getMapIndex());
            }
        }
    }

    /**
     * 地图下移
     */
    public void moveDown() {
        //先拿出当前地图第二行的数据
        List<DigGoldBlockData> secondLineBlock = getBlockDataByY(userData.getInCol() + 1, userData.getBlockDataList());
        //检测他们的联通
        for (DigGoldBlockData blockData:secondLineBlock){
            checkConnectTop(blockData.getX(),blockData.getY());
        }
        //然后再下移一行
        userData.setInCol(userData.getInCol() + 1);
        //如果跨过上地图 就要生成新的地图了
        if (userData.getInCol() >= (DigGoldMgr.getBoardY() * userData.getMapIndex())) {
            //需要移除的地图索引
            int needRemoveIndex = userData.getMapIndex() - 1;
            //生成新的地图
            List<DigGoldBlockData> digGoldBlockData = DigGoldMgr.getMapByIndex(userData.getMapIndex() + 1,userData);
            if (digGoldBlockData == null || digGoldBlockData.size() != DigGoldMgr.getBoardX() * DigGoldMgr.getBoardY()) {
                userData.setUpdateOption();
                log.error("DigGoldModule moveDown generateRandomMapData error userId:{},mapIndex:{}",userData.getUserId() , userData.getMapIndex() + 1);
                return;
            }
            userData.getBlockDataList().removeIf(blockData -> blockData.getMap() == needRemoveIndex);
            //加新的
            userData.getBlockDataList().addAll(digGoldBlockData);
            //地图索引+1
            userData.setMapIndex(userData.getMapIndex() + 1);
            //移除领取宝箱的记录
            userData.getBoxList().remove(needRemoveIndex);

            boolean isPalace = false;
            for (DigGoldBlockData blockData : digGoldBlockData) {
                if (blockData.getType() == eDigGoldBlockType.palace.getValue()) {
                    isPalace = true;
                    break;
                }
            }
            //添加新的领取宝箱的记录
            userData.getBoxList().put(userData.getMapIndex(), DigGoldMgr.getBoxMapByIndex(isPalace));
            if (isPalace){
                userData.setNoPalaceTime(0);
            }else {
                userData.setNoPalaceTime(userData.getNoPalaceTime() + 1);
            }

        }
        userData.setUpdateOption();
        //syncUserData();
    }

    /**
     * 检测是否与顶部联通
     * @param blockData
     * @return
     */
    public int checkConnectTop(DigGoldBlockData blockData) {
        if (blockData == null){
            return GameErrorCode.E_DIG_GOLD_BLOCK_NOT_EXIST;
        }
        int inCol = userData.getInCol();            //玩家的第一行在地图的第几列 0-6
        int endCol = inCol + DigGoldMgr.getBoardY() - 1;   //玩家的最后一行在地图的第几列
        if (blockData.getY() > endCol) {                        //如果是在玩家的最后一行之后 不操作
            return GameErrorCode.E_DIG_GOLD_BLOCK_BEYOND_MAP;
        }
        if (blockData.getY() < inCol) {                         //如果是在玩家的第一行之前 不操作
            return GameErrorCode.E_DIG_GOLD_BLOCK_BEYOND_MAP;
        }
        if (blockData.isLinkTop()){
            return 0;
        }
        //获取当前盘面上的所有方块
        List<DigGoldBlockData> blockDataByY = getBlockDataByYRange(inCol, endCol, userData.getBlockDataList());
        //相近的方块
        List<DigGoldBlockData> hasList = new ArrayList<>();
        //将当前方块加入相近的方块
        hasList.add(blockData);

        //栈初始化 每次从一个新方块开始遍历都需要初始化栈
        Stack<DigGoldBlockData> stack = new Stack<>();
        //推入栈内
        stack.push(blockData);

        DigGoldBlockData tmpBlockData = blockData;
        while (!stack.isEmpty()) {
            DigGoldBlockData newNearBlock = getNewNearBlock(blockDataByY, tmpBlockData, hasList, inCol, endCol);
            if (newNearBlock != null) {
//                //如果这个方块是空方块或者地宫方块 并且在玩家的第一行及之前
//                if (newNearBlock.getY() <= inCol) {
//                    newNearBlock.setLinkTop(true);
//                }
                stack.push(newNearBlock);
                hasList.add(newNearBlock);
                tmpBlockData = stack.peek();
            } else {
                stack.pop();
                if (stack.isEmpty()) {
                    break;
                }
                tmpBlockData = stack.peek();
            }
        }
        for (DigGoldBlockData data : hasList) {
            if (data.equals(blockData)) {
                continue;
            }
            if (data.getY() <= inCol && data.isLinkTop()) {
                blockData.setLinkTop(true);
                return 0;
            }
        }
        return GameErrorCode.E_DIG_GOLD_BLOCK_NO_CONNECT_TOP;
    }

    /**
     * 修复数据
     * @param index
     */

    public void fixUserBoard(int index){
        List<DigGoldBlockData> upperMapByIndex = DigGoldMgr.getMapByIndex(index, userData);
        if (upperMapByIndex == null || upperMapByIndex.isEmpty()){
            log.error("userId = {} fix dig gold error", getUserId());
            return;
        }
        List<DigGoldBlockData> downMapByIndex = DigGoldMgr.getMapByIndex(index+1, userData);
        if (downMapByIndex == null || downMapByIndex.isEmpty()){
            log.error("userId = {} fix dig gold error", getUserId());
            return;
        }
        userData.getBoxList().put(index,DigGoldMgr.getBoxMapByIndex(false));
        userData.getBoxList().put(index+1,DigGoldMgr.getBoxMapByIndex(false));
        upperMapByIndex.addAll(downMapByIndex);
        userData.setBlockDataList(upperMapByIndex);
        userData.setInCol(DigGoldMgr.getBoardY() * index);

    }

    /**
     * 检测是否与顶部联通
     * @param x
     * @param y
     * @return
     */
    public int checkConnectTop(int x, int y) {

        int inCol = userData.getInCol();            //玩家的第一行在地图的第几列 0-6
        int endCol = inCol + DigGoldMgr.getBoardY() - 1;   //玩家的最后一行在地图的第几列

        if (y > endCol) {                        //如果是在玩家的最后一行之后 不操作
            return GameErrorCode.E_DIG_GOLD_BLOCK_BEYOND_MAP;
        }

        if (y < inCol) {                         //如果是在玩家的第一行之前 不操作
            return GameErrorCode.E_DIG_GOLD_BLOCK_BEYOND_MAP;
        }
        //拿出操作的方块
        DigGoldBlockData blockData = getBlockDataByXY(x, y, userData.getBlockDataList());
        if (blockData == null) {
            return GameErrorCode.E_DIG_GOLD_BLOCK_NO_EXIST;
        }
        if (blockData.isLinkTop()){
            return 0;
        }
        //获取当前盘面上的所有方块
        List<DigGoldBlockData> blockDataByY = getBlockDataByYRange(inCol, endCol, userData.getBlockDataList());
        //相近的方块
        List<DigGoldBlockData> hasList = new ArrayList<>();
        //将当前方块加入相近的方块
        hasList.add(blockData);

        //栈初始化 每次从一个新方块开始遍历都需要初始化栈
        Stack<DigGoldBlockData> stack = new Stack<>();
        //推入栈内
        stack.push(blockData);

        DigGoldBlockData tmpBlockData = blockData;
        while (!stack.isEmpty()) {
            DigGoldBlockData newNearBlock = getNewNearBlock(blockDataByY, tmpBlockData, hasList, inCol, endCol);
            if (newNearBlock != null) {
//                //如果这个方块是空方块或者地宫方块 并且在玩家的第一行及之前
//                if (newNearBlock.getY() <= inCol) {
//                    newNearBlock.setLinkTop(true);
//                }
                stack.push(newNearBlock);
                hasList.add(newNearBlock);
                tmpBlockData = stack.peek();
            } else {
                stack.pop();
                if (stack.isEmpty()) {
                    break;
                }
                tmpBlockData = stack.peek();
            }
        }
        for (DigGoldBlockData data : hasList) {
            if (data.equals(blockData)) {
                continue;
            }
            if (data.getY() <= inCol && data.isLinkTop()) {
                blockData.setLinkTop(true);
                return 0;
            }
        }
        return GameErrorCode.E_DIG_GOLD_BLOCK_NO_CONNECT_TOP;
    }

    /**
     * 获取相邻的空方块或地宫方块
     */
    public DigGoldBlockData getNewNearBlock(List<DigGoldBlockData> blockData, DigGoldBlockData targetData, List<DigGoldBlockData> hasList, int startCol, int endCol) {
        if (targetData.getX() > 0) {
            DigGoldBlockData leftBlock = getBlockDataByXY(targetData.getX() - 1, targetData.getY(), blockData);
            if (leftBlock != null && (leftBlock.getType() == eDigGoldBlockType.space.getValue() || leftBlock.getType() == eDigGoldBlockType.palace.getValue()) && !hasList.contains(leftBlock)) {
                return leftBlock;
            }

        }
        if (targetData.getX() < DigGoldMgr.getBoardX() - 1) {
            DigGoldBlockData rightBlock = getBlockDataByXY(targetData.getX() + 1, targetData.getY(), blockData);
            if (rightBlock != null && (rightBlock.getType() == eDigGoldBlockType.space.getValue() || rightBlock.getType() == eDigGoldBlockType.palace.getValue()) && !hasList.contains(rightBlock)) {
                return rightBlock;
            }
        }
        if (targetData.getY() > startCol) {
            DigGoldBlockData topBlock = getBlockDataByXY(targetData.getX(), targetData.getY() - 1, blockData);
            if (topBlock != null && (topBlock.getType() == eDigGoldBlockType.space.getValue() || topBlock.getType() == eDigGoldBlockType.palace.getValue()) && !hasList.contains(topBlock)) {
                return topBlock;
            }
        }
        if (targetData.getY() < endCol) {
            DigGoldBlockData bottomBlock = getBlockDataByXY(targetData.getX(), targetData.getY() + 1, blockData);
            if (bottomBlock != null && (bottomBlock.getType() == eDigGoldBlockType.space.getValue() || bottomBlock.getType() == eDigGoldBlockType.palace.getValue()) && !hasList.contains(bottomBlock)) {
                return bottomBlock;
            }
        }
        return null;
    }


    /**
     * 从开始行的y到结束行的y获取所有方块
     */
    public List<DigGoldBlockData> getBlockDataByYRange(int startY, int endY, List<DigGoldBlockData> blockDataList) {
        List<DigGoldBlockData> tmpBlockDataList = new ArrayList<>();
        if (blockDataList == null || blockDataList.size() == 0) {
            return null;
        }
        for (DigGoldBlockData blockData : blockDataList) {
            if (blockData.getY() >= startY && blockData.getY() <= endY) {
                tmpBlockDataList.add(blockData);
            }
        }
        return tmpBlockDataList;
    }


    /**
     * 根据类型获取方块
     *
     * @param type
     * @return
     */
    public List<DigGoldBlockData> getBlockDataByType(int type, List<DigGoldBlockData> blockDataList) {
        List<DigGoldBlockData> tmpBlockDataList = new ArrayList<>();
        if (blockDataList == null || blockDataList.size() == 0) {
            return null;
        }
        for (DigGoldBlockData blockData : blockDataList) {
            if (blockData.getType() == type) {
                tmpBlockDataList.add(blockData);
            }
        }
        return tmpBlockDataList;
    }

    /**
     * 根据y获取所有同行方块
     *
     * @param Y
     * @return
     */
    public List<DigGoldBlockData> getBlockDataByY(int Y, List<DigGoldBlockData> blockDataList) {
        List<DigGoldBlockData> tmpBlockDataList = new ArrayList<>();

        if (blockDataList == null || blockDataList.size() == 0) {
            return null;
        }
        for (DigGoldBlockData blockData : blockDataList) {
            if (blockData.getY() == Y) {
                tmpBlockDataList.add(blockData);
            }
        }
        return tmpBlockDataList;
    }


    /**
     * 根据x获取所有同列方块
     *
     * @param x
     * @return
     */

    public List<DigGoldBlockData> getBlockDataByX(int x, List<DigGoldBlockData> blockDataList) {
        List<DigGoldBlockData> tmpBlockDataList = new ArrayList<>();

        if (blockDataList == null || blockDataList.size() == 0) {
            return null;
        }
        for (DigGoldBlockData blockData : blockDataList) {
            if (blockData.getX() == x) {
                tmpBlockDataList.add(blockData);
            }
        }
        return tmpBlockDataList;
    }

    /**
     * 根据地图坐标获取方块数据
     *
     * @param x
     * @param y
     * @return
     */

    public DigGoldBlockData getBlockDataByXY(int x, int y, List<DigGoldBlockData> blockDataList) {

        if (blockDataList == null || blockDataList.size() == 0) {
            return null;
        }
        for (DigGoldBlockData blockData : blockDataList) {
            if (blockData.getX() == x && blockData.getY() == y) {
                return blockData;
            }
        }
        return null;
    }


    /**
     * 根据地图下标获取方块数据
     *
     * @param mapIndex
     * @return
     */
    public List<DigGoldBlockData> getBlockDataByIndex(int mapIndex, List<DigGoldBlockData> blockDataList) {
        List<DigGoldBlockData> tmpBlockDataList = new ArrayList<>();
        if (blockDataList == null || blockDataList.size() == 0) {
            return null;
        }
        for (DigGoldBlockData blockData : blockDataList) {
            if (blockData.getMap() == mapIndex) {
                tmpBlockDataList.add(blockData);
            }
        }
        return tmpBlockDataList;
    }

    /**
     * 玩家数据解析成消息
     */
    public DigGoldProto.DigGoldUserData.Builder parseUserData() {
        DigGoldProto.DigGoldUserData.Builder builder = DigGoldProto.DigGoldUserData.newBuilder();
        builder.setInCol(userData.getInCol());
        builder.setMapIndex(userData.getMapIndex());
        for (Map.Entry<Integer, List<Integer>>entry : userData.getBoxList().entrySet()) {
            DigGoldProto.DigGoldBoxData.Builder boxBuilder = DigGoldProto.DigGoldBoxData.newBuilder();
            boxBuilder.setMapIndex(entry.getKey());
            boxBuilder.addAllBoxIndex(entry.getValue());
            builder.addBox(boxBuilder);
        }
        for (Map.Entry<Integer,Integer> entry:userData.getAntiqueNumMap().entrySet()){
            DigGoldProto.DigGoldAntiqueData.Builder antiqueBuilder = DigGoldProto.DigGoldAntiqueData.newBuilder();
            antiqueBuilder.setAntiqueId(entry.getKey());
            antiqueBuilder.setNum(entry.getValue());
            builder.addAntiqueData(antiqueBuilder);
        }

        builder.addAllBlocks(parseBlockDataList(userData.getBlockDataList()));
        builder.setScore(userData.getScore());
        builder.setAntiqueScore(userData.getAntiqueScore());
        for (Map.Entry<Integer,Integer>entry:userData.getStratumIndexMap().entrySet()){
            DigGoldProto.DigGoldUserStratumData.Builder stratumBuilder = DigGoldProto.DigGoldUserStratumData.newBuilder();
            stratumBuilder.setStratumId(entry.getKey());
            stratumBuilder.setUnlockIndex(entry.getValue());
            builder.addStratumData(stratumBuilder);
        }

        return builder;
    }

    public List<DigGoldProto.DigGoldBlockData> parseBlockDataList(List<DigGoldBlockData> blockDataList) {
        List<DigGoldProto.DigGoldBlockData> builderList = new ArrayList<>();
        for (DigGoldBlockData blockData : blockDataList) {
            builderList.add(parseBlockData(blockData).build());
        }
        return builderList;
    }

    /**
     * 方块解析成消息
     *
     * @param blockData
     * @return
     */
    public DigGoldProto.DigGoldBlockData.Builder parseBlockData(DigGoldBlockData blockData) {
        DigGoldProto.DigGoldBlockData.Builder builder = DigGoldProto.DigGoldBlockData.newBuilder();
        builder.setX(blockData.getX());
        builder.setY(blockData.getY());
        builder.setType(blockData.getType());
        builder.setHp(blockData.getHp());
        builder.setMapIndex(blockData.getMap());
        builder.setReward(blockData.getReward());
        builder.setIsConnected(blockData.isLinkTop());
        return builder;
    }


}
